package spoon.service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import spoon.core.domain.Game;
import spoon.core.exception.ConvertException;

public abstract class TenbetAbstractService implements TenbetService {

	@Autowired
	protected TenbetHttpService tenbetHttpService;

	@Value("#{tenbet['site']}")
	protected String SITE;

	@Value("#{tenbet['url']}")
	protected String URL;

	@Value("#{tenbet['link']}")
	protected String LINK;

	protected String GATE_URL;

	protected String ITEM_CODE;

	protected String ITEM_NAME;
	
	// 리그별 링크 정보를 가지고 있는 소스
	protected String LINK_CODE;

	protected Map<String, String> leagueMap;

	protected Map<String, String> teamMap;
	
	protected Map<String, String> typeMap;
	
	protected Map<String, String> linkMap = new HashMap<String, String>();

	protected Logger log = LoggerFactory.getLogger(this.getClass());

	@Override
	public abstract List<Game> getLeagueList();

	@Override
	public abstract void getLeague(Game leauge);
	
	
	protected void setTypeMap(String type) {
		log.info("{}", type);
	}
	
	/**
	 * 리그코드 변경
	 * 
	 * @param league
	 * @return
	 */
	protected String getLeagueCode(String league) {
		String leagueCode = leagueMap.get(league);
		if (leagueCode == null || "".equals(leagueCode)) {
			leagueCode = league;
			// log.error("{} {} 리그코드 변경에러, 리그명 = {}", SITE, ITEM_NAME, league);
		}
		return leagueCode;
	}

	/**
	 * 팀코드 변경
	 * 
	 * @param team
	 * @return
	 */
	protected String getTeamCode(String team) {
		String teamCode = teamMap.get(team);
		if (teamCode == null || "".equals(teamCode)) {
			teamCode = team;
			// log.error("{} {} 팀코드 변경에러, 팀명 = {}", SITE, ITEM_NAME, team);
		}
		return teamCode;
	}
	
	/**
	 * 날짜 변환 표준시간으로 변환
	 * 
	 * @param dt
	 * @return
	 */
	protected Date convertDate(String dt) {
		
		dt = dt.replaceAll("T", "").replaceAll(".0000000", "");
		
		DateFormat df = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss");
		TimeZone tz = TimeZone.getTimeZone("Greenwich");
		df.setTimeZone(tz);

		Date date = new Date();
		try {
			date = df.parse(dt);
		} catch (ParseException e) {
			throw new ConvertException(new Throwable(SITE + " " + ITEM_NAME + " 날짜변경 에러 (" + dt + ")", e));
		}
		return date;
	}

	/**
	 * 배당변환 분수 형태를 소수점 형태로
	 * 
	 * @param rate
	 * @return
	 */
	protected Double convertRate(String rate) {
		if (rate == null || "".equals(rate)) {
			return 0D;
		}
		
		Double d = 0D;
		// 배당은 +로 된 배당과 - 로 된 배당이 있다.
		int r = Integer.parseInt(rate);
		if (r > 0) {
			d = 1 + r / 100D;
		} else {
			d = 1 - 100D / r;
		}
		
		return Double.parseDouble(String.format("%.2f", d - 0.005));
	}

	/**
	 * 핸디캡 변환
	 * 
	 * @param handicap
	 * @return
	 */
	protected Double convertHandicap(String handicap) {
		Double d = null;

		if (handicap == null || "".equals(handicap)) {
			d = 0D;
		} else if (handicap.contains(",")) {
			String[] hs = handicap.split(",");
			d = (Double.parseDouble(hs[0]) + Double.parseDouble(hs[1])) / 2D;
		} else {
			d = Double.parseDouble(handicap);
		}

		return d;
	}
	
	protected String convertLink(String source) {

		Pattern p = Pattern.compile("\\[([0-9]+),([0-9]+),,,,([0-9]+)");
		Matcher m = p.matcher(source);
		
		String param = "requestString=";
		boolean isFirst = true;
		
		while(m.find()) {
			if (isFirst) {
				param += m.group(1);
			} else {
				param += "@" + m.group(1);
			}
			isFirst = false;
			
			linkMap.put(m.group(1), getBettingType(m.group(2)));
		}
		
		return param;
	}
	
	protected String getBettingType(String code) {
		
		Pattern p = Pattern.compile("\\[" + code + ",\\\"([^\\\"]+)\\\"");
		Matcher m = p.matcher(LINK_CODE);
		String betCode = "";
		
		if (m.find()) {
			log.info("{}", m.group(1));
			betCode = m.group(1);
		} else {
			log.error("{} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", code);
		}
		
		return betCode;
	}
	
	protected void betMatch(Game game, String source) {
		// Over Under. 1: 핸디캡, 2: 승배당, 3: 패배당
		String pattern = "\\[[0-9]+,([0-9.-]+),([0-9-]+),[0-9]+,([0-9-]+)\\],[01],";
		Pattern p = Pattern.compile(pattern);
		Matcher m = p.matcher(source);

		while (m.find()) {
			// Over
			Game betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("OU");
			betting.setBetName("Over/Under");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(2)));
			betting.setBetRateName(m.group(2));
			betting.setBetRateCode("Over");
			game.addGameList(betting);
			
			// Under
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("OU");
			betting.setBetName("Over/Under");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(3)));
			betting.setBetRateName(m.group(3));
			betting.setBetRateCode("Under");
			game.addGameList(betting);
		}
		
		// Asian Handicap
		source = source.replaceAll(pattern, "");
		pattern = "\\[[0-9]+,([0-9.-]+),([0-9-]+),[0-9]+,([0-9-]+)\\]";
		
		p = Pattern.compile(pattern);
		m = p.matcher(source);
		
		while (m.find()) {
			Game betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("H");
			betting.setBetName("Asian Handicap");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(2)));
			betting.setBetRateName(game.getHomeTeamCode());
			betting.setBetRateCode("1");
			game.addGameList(betting);
			
			// Under
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("H");
			betting.setBetName("Asian Handicap");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(3)));
			betting.setBetRateName(game.getAwayTeamCode());
			betting.setBetRateCode("2");
			game.addGameList(betting);
		}
		
		// 1X2
		source = source.replaceAll(pattern, "");
		
		p = Pattern.compile("\\[[0-9]+,([0-9-]+),[0-9]+,([0-9-]+),[0-9]+,([0-9-]+)\\]");
		m = p.matcher(source);
		
		while (m.find()) {
			Game betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("1X2");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(m.group(1)));
			betting.setBetRateName(game.getHomeTeamCode());
			betting.setBetRateCode("1");
			game.addGameList(betting);
			
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("1X2");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(m.group(2)));
			betting.setBetRateName("Draw");
			betting.setBetRateCode("X");
			game.addGameList(betting);
			
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("1X2");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(m.group(3)));
			betting.setBetRateName(game.getAwayTeamCode());
			betting.setBetRateCode("2");
			game.addGameList(betting);
		}
	}

	protected void betDrawNoBet(Game game, String source) {
		
		Pattern p = Pattern.compile("\\[[0-9]+,([0-9.-]+),([0-9-]+),[0-9]+,([0-9-]+)\\]");
		Matcher m = p.matcher(source);

		while (m.find()) {
			// Over
			Game betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("DNB");
			betting.setBetName("Draw No Bet");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(2)));
			betting.setBetRateName(m.group(2));
			betting.setBetRateCode("1");
			game.addGameList(betting);
			
			// Under
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("DNB");
			betting.setBetName("Draw No Bet");
			betting.setHandicap(convertHandicap(m.group(1)));
			betting.setHandicapName(m.group(1));
			betting.setBetRate(convertRate(m.group(3)));
			betting.setBetRateName(m.group(3));
			betting.setBetRateCode("2");
			game.addGameList(betting);
		}
	}
	
	protected void betCorners(Game game, String source) {
		
	}
	
	
}
